// Oren-Nayar shading model fragment shader
// Have to be used with FragmentShaderFunctions.frag

uniform float fAlbedo;
uniform float fGaussianVariance;

varying vec2 Texcoord;
varying vec3 ViewDirection;
varying vec3 LightDirection;
varying float Distance;

vec4 fvGetOrenNayarIllumination(vec2 texCoord, int index)
{
   vec3 l = normalize( LightDirection );
   vec3 v = normalize( ViewDirection );
   vec3 n = normalize( ( texture2D( bumpMap, texCoord ).xyz * 2.0 ) - 1.0 );
    
   float alpha = max( acos( dot( v, n ) ), acos( dot( l, n ) ) );
   float beta = min( acos( dot( v, n ) ), acos( dot( l, n ) ) );
   float gamma = dot( v - n * dot( v, n ), l - n * dot( l, n ) );
   float rough_sq = fRoughness * fRoughness;
   
   float C1 = 1.0 - 0.5 * ( rough_sq / ( rough_sq + 0.33 ) );
 
   float C2 = 0.45 * ( rough_sq / ( rough_sq + 0.09 ) );
   if( gamma >= 0.0 ) C2 *= sin( alpha );
   else C2 *= ( sin( alpha ) - pow( (2.0 * beta) / PI, 3.0 ) );
 
   float C3  = (1.0 / 8.0) ;
   C3 *= ( rough_sq / ( rough_sq + 0.09 ) );
   C3 *= pow( ( 4.0 * alpha * beta ) / (PI * PI), 2.0 );
 
   float A = gamma * C2 * tan( beta );
   float B = (1.0 - abs( gamma )) * C3 * tan( (alpha + beta) / 2.0 );

   float fAttenuation = 2.0 / (fvAttenuation.x + 
                               fvAttenuation.y * Distance + 
                               fvAttenuation.z * Distance * Distance);
                               
   vec4 fvTotalDiffuse = fvDiffuse * (fAlbedo / PI) * 
                         max( 0.0, dot( n, l ) ) * ( C1 + A + B );
   
   return fvTotalDiffuse * fAttenuation;
}
